/*-----------------------------------------------------------------------*/
/* Low level disk I/O module skeleton for FatFs     (C)ChaN, 2019        */
/*-----------------------------------------------------------------------*/
/* If a working storage control module is available, it should be        */
/* attached to the FatFs via a glue function rather than modifying it.   */
/* This is an example of glue functions to attach various exsisting      */
/* storage control modules to the FatFs module with a defined API.       */
/*-----------------------------------------------------------------------*/

#include "ff.h"			/* Obtains integer types */
#include "diskio.h"		/* Declarations of disk functions */
#include "w25qxx.h"

/* Definitions of physical drive number for each drive */
#define SPI_FLASH		0	/* Example: Map Ramdisk to physical drive 0 */


/*-----------------------------------------------------------------------*/
/* Get Drive Status                                                      */
/*-----------------------------------------------------------------------*/

DSTATUS disk_status (
	BYTE pdrv		/* Physical drive nmuber to identify the drive */
)
{
	DSTATUS stat;

	switch (pdrv) {
	case SPI_FLASH :
		if(W25QXX_ReadID()==sFLASH_ID){
			stat=!STA_NOINIT;
		}else{
			stat=STA_NOINIT;
		}
		return stat;
	}
	return STA_NOINIT;
}



/*-----------------------------------------------------------------------*/
/* Inidialize a Drive                                                    */
/*-----------------------------------------------------------------------*/

DSTATUS disk_initialize (
	BYTE pdrv				/* Physical drive nmuber to identify the drive */
)
{
	DSTATUS stat;

	switch (pdrv) {
	case SPI_FLASH :
		W25QXX_Initialization();
		stat=disk_status(SPI_FLASH);
		return stat;
	}
	return STA_NOINIT;
}



/*-----------------------------------------------------------------------*/
/* Read Sector(s)                                                        */
/*-----------------------------------------------------------------------*/

DRESULT disk_read (
	BYTE pdrv,		/* Physical drive nmuber to identify the drive */
	BYTE *buff,		/* Data buffer to store read data */
	LBA_t sector,	/* Start sector in LBA */
	UINT count		/* Number of sectors to read */
)
{
	DRESULT res;

	switch (pdrv) {
	case SPI_FLASH :
		W25QXX_BufferRead((u8*)buff,sector<<12,count<<12);
		res=RES_OK;
		return res;
	}
	return RES_PARERR;
}



/*-----------------------------------------------------------------------*/
/* Write Sector(s)                                                       */
/*-----------------------------------------------------------------------*/

#if FF_FS_READONLY == 0

DRESULT disk_write (
	BYTE pdrv,			/* Physical drive nmuber to identify the drive */
	const BYTE *buff,	/* Data to be written */
	LBA_t sector,		/* Start sector in LBA */
	UINT count			/* Number of sectors to write */
)
{
	DRESULT res;

	switch (pdrv) {
	case SPI_FLASH :
		W25QXX_SectorEraseFun(sector<<12);
		W25QXX_BufferWrite((u8*)buff,sector<<12,count<<12);
		res=RES_OK;
		return res;
	}
	return RES_PARERR;
}

#endif


/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions                                               */
/*-----------------------------------------------------------------------*/

DRESULT disk_ioctl (
	BYTE pdrv,		/* Physical drive nmuber (0..) */
	BYTE cmd,		/* Control code */
	void *buff		/* Buffer to send/receive control data */
)
{
	DRESULT res;

	switch (pdrv) {
	case SPI_FLASH :
		switch (cmd) {
			/* 扇区数量：1536*4096/1024/1024=6(MB) */
			case GET_SECTOR_COUNT:
				*(DWORD*)buff=4096;		
				break;
			/* 扇区大小  */
			case GET_SECTOR_SIZE :
				*(WORD*)buff=4096;
				break;
			/* 同时擦除扇区个数 */
			case GET_BLOCK_SIZE :
				*(DWORD*)buff=1;
				break;
		}
		res=RES_OK;
		return res;
	}
	return RES_PARERR;
}

DWORD get_fattime (void)
{
	return ((DWORD)(2015-1980)<<25)	/* Year 2015 */
				|((DWORD)1<<21)				/* Month 1 */
				|((DWORD)1<<16)				/* Mday 1 */
				|((DWORD)0<<11)				/* Hour 0 */
				|((DWORD)0<<5)				  /* Min 0 */
				|((DWORD)0>>1);				/* Sec 0 */
}

